package com.loan.web.pdf.controller;

import com.loan.common.core.domain.AjaxResult;
import com.loan.common.utils.SecurityUtils;
import com.loan.common.utils.StringUtils;
import com.loan.common.utils.file.FileUtils;
import com.loan.system.create.domain.AssistPdfCreateFile;
import com.loan.system.create.service.IAssistPdfCreateFileService;
import com.loan.system.domain.AssistFile;
import com.loan.system.domain.AssistType;
import com.loan.system.domain.pdf.QueryVo;
import com.loan.system.domain.pdf.ResultDomain;
import com.loan.system.domain.work.domain.*;
import com.loan.system.service.IAssistFileService;
import com.loan.system.service.IAssistTypeService;
import com.loan.system.service.IDealPdfServiceTemp;
import com.loan.system.utils.ReplacePdf;
import com.loan.web.conf.PdfConf;
import com.loan.web.utils.ExportBankUtil;
import com.loan.web.utils.ExtractorBankUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/pdf")
public class PdfDealController {

    @Autowired
    private PdfConf pdfConf;
    @Autowired
    private ReplacePdf pdfTemp;
    @Autowired
    private IAssistFileService assistFileService;
    @Autowired
    private IAssistTypeService assistTypeService;
    @Autowired
    private IDealPdfServiceTemp dealPdfServiceTemp;
    @Autowired
    private IAssistPdfCreateFileService assistPdfCreateFileService;
    @Autowired
    private ExtractorBankUtil extractorBankUtil;
    @Autowired
    private ExportBankUtil exportBankUtil;

    /**
     * 业务逻辑步骤
     * 1、上传文件
     * 2、解析文件并返回原始数据和要处理的数组大小
     * 3、根据入参随机生成数组大小的随机数并映射封装
     * 4、页面回显封装映射并可修改随机数
     * 5、提交完成随机数的修改
     * 6、下载文件
     */

    /**
     * 1、上传文件到服务器
     *
     * @param vo 文件及附带参数信息
     * @return
     */
    @PostMapping("/uploadPdfFile")
    public AjaxResult uploadPdfFile(QueryVo vo) {
        AssistFile assistFile = new AssistFile();
        try {
            log.info("上传PDF文件...");
            MultipartFile file = vo.getFile();
            Long assistTypeId = vo.getAssistTypeId();
            AssistType assistType = assistTypeService.selectAssistTypeById(assistTypeId);
            String originalFilePathDir = assistType.getOriginalFilePath();
            String targetFilePathDir = assistType.getTargetFilePath();
            String[] split = file.getOriginalFilename().split("\\.");
            String originalFileName = split[0];
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
            Date date = new Date();
            String dateStr = sdf.format(date);
            String fileName = String.format("%s-%s.pdf", originalFileName, dateStr);
            String targetFileName = String.format("target-%s-%s.pdf", originalFileName, dateStr);
            String filePath = originalFilePathDir + fileName;
            String targetFilePath = targetFilePathDir + targetFileName;
            File f = new File(filePath);
            FileCopyUtils.copy(file.getBytes(), f);
            // 获取当前登录人信息
            Long userId = SecurityUtils.getLoginUser().getUserId();
            assistFile.setUserId(userId);
            assistFile.setOriginalFileName(fileName);
            assistFile.setOriginalFilePath(filePath);
            assistFile.setNewFileName(targetFileName);
            assistFile.setNewFilePath(targetFilePath);
            assistFile.setAssistTypeId(assistTypeId);
            assistFile.setCreateTime(date);
            assistFile.setUpdateTime(date);
            assistFileService.insertAssistFile(assistFile);
            log.info("文件上传并记录成功！");

        } catch (Exception e) {
            log.error("文件上传出现异常: {}", e.getMessage());
            log.error(e.getMessage(), e);
            return AjaxResult.error("文件上传出现异常：{}", e.getMessage());
        }
        return AjaxResult.success(assistFile);
    }

    /**
     * 2、解析文件并返回原始数据和要处理的数组大小
     *
     * @param fileId 文件唯一标识
     * @return
     */
    @GetMapping("/getFileTextById/{fileId}")
    public AjaxResult getFileText(@PathVariable("fileId") Long fileId) {
        log.info("根据文件id获取上传文件信息：{}", fileId);
        AssistFile assistFile = assistFileService.selectAssistFileById(fileId);
        log.info("获取原始数据信息...");
        ResultDomain result = dealPdfServiceTemp.getOriginalInfoAndDealSize(assistFile);
        result.setAssistFile(assistFile);
        return AjaxResult.success(result);
    }

    /**
     * 3、根据入参随机生成数组大小的随机数并映射封装
     *
     * @param result
     * @return
     */
    @PostMapping("/createRomValueMapping")
    public AjaxResult createRomValueMapping(@RequestBody ResultDomain result) {
        log.info("根据入参随机生成数组大小的随机数并映射封装...");
        ResultDomain resultDomain = dealPdfServiceTemp.createRomValueMapping(result);
        return AjaxResult.success(resultDomain);
    }

    /**
     * 4、页面回显封装映射并可修改随机数
     */

    /**
     * 5、提交完成随机数的修改并完成文件修改
     */
    @PostMapping("/dealPdfToFile")
    public AjaxResult dealPdfAndCreateFile(@RequestBody ResultDomain resultDomain) {
        log.info("处理数据并生成PDF新文件...");
        AssistFile assistFile = dealPdfServiceTemp.dealPdfTextAndCreateFile(resultDomain);
        return AjaxResult.success(assistFile);
    }

    /**
     * 6、下载文件
     */
    @GetMapping("/download/{fileId}")
    public void fileDownload(@PathVariable("fileId") Long fileId, HttpServletResponse response) {
        try {
            log.info("下载处理完成的文件：{}", fileId);
            String filePath = "";
            String realFileName = "";
            AssistFile assistFile = assistFileService.selectAssistFileById(fileId);
            if (assistFile != null) {
                filePath = assistFile.getNewFilePath();
                realFileName = assistFile.getNewFileName();
            } else {
                AssistPdfCreateFile assistPdfCreateFile = assistPdfCreateFileService.selectAssistPdfCreateFileById(fileId);
                filePath = assistPdfCreateFile.getPdfFilePath();
                // realFileName = assistPdfCreateFile.getPdfFileName();
                realFileName = FileUtils.getName(filePath);
                // 将下载次数加一
                assistPdfCreateFile.setInNum(assistPdfCreateFile.getInNum() != null ? (assistPdfCreateFile.getInNum() + 1) : 1);
                assistPdfCreateFileService.updateAssistPdfCreateFile(assistPdfCreateFile);
            }
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败: {}", e.getMessage());
            log.error(e.getMessage(), e);
        }
    }

    @GetMapping("/getAssistTypeList")
    public AjaxResult getAssistTypeList() {
        log.info("查询所有功能类型数据...");
        List<AssistType> list = assistTypeService.getAssistTypeList();
        return AjaxResult.success(list);
    }

    @PostMapping("/dealInAndOut")
    public AjaxResult dealPDFInAndOut(QueryVo vo,
                                      HttpServletResponse response) {
        ResultDomain resultDomain = new ResultDomain();
        try {
            MultipartFile file = vo.getFile();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
            String format = sdf.format(new Date());
            String filePath = String.format(pdfConf.getFilePath(), format);
            String targetFilePath = String.format(pdfConf.getTargetFilePath(), format);
            File f = new File(filePath);
            FileCopyUtils.copy(file.getBytes(), f);
            String absolutePath = f.getAbsolutePath();

            resultDomain = pdfTemp.dealPdfFun(absolutePath, targetFilePath, vo);
        } catch (Exception e) {
            log.error("出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
        }
        return AjaxResult.success(resultDomain);
    }

    /**
     * 获取JH数据列表
     *
     * @param jhVo
     * @return
     */
    @PostMapping("/getJhDetailList")
    public AjaxResult getJhDetailList(@RequestBody JhVo jhVo) {
        log.info("获取JH数据入参：{}", jhVo);
        List<JhPdfDomain> list = extractorBankUtil.compJhDataDetail(jhVo.getSeqNo(), jhVo.getStartTime(), jhVo.getEndTime(), jhVo.getOriginalMoney(), jhVo.getTotalInMoney(), jhVo.getTotalOutMoney());
        List<JhPdfDomain> inValueList = new ArrayList<>();
        List<JhPdfDomain> outValueList = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.equals(item.getTransactionType(), "+")) {
                // 收
                inValueList.add(item);
            } else {
                outValueList.add(item);
            }
        });
        jhVo.setInValueList(inValueList);
        jhVo.setOutValueList(outValueList);
        return AjaxResult.success(jhVo);
    }


    /**
     * 生成PDF文件
     *
     * @param jhVo
     * @throws IOException
     */
    @PostMapping("/createJhPdf")
    public AjaxResult createJhPdf(@RequestBody JhVo jhVo) throws Exception {
        jhVo.setTypeId(2l);
        List<JhPdfDomain> inValueList = jhVo.getInValueList();
        List<JhPdfDomain> outValueList = jhVo.getOutValueList();

        if (!(inValueList != null && !inValueList.isEmpty())) {
            log.info("收入明细数据无效，请检查!");
            return AjaxResult.error("收入明细数据无效，请检查");
        }
        if (!(outValueList != null && !outValueList.isEmpty())) {
            log.info("支出明细数据无效，请检查!");
            return AjaxResult.error("支出明细数据无效，请检查");
        }
        log.info("合并支出并按照时间日期排序...");
        List<JhPdfDomain> needSortDataList = new ArrayList<>();
        needSortDataList.addAll(inValueList);
        needSortDataList.addAll(outValueList);
        List<JhPdfDomain> sortedDataList = needSortDataList.stream().sorted(Comparator.comparingInt(JhPdfDomain::getSeqNo)).collect(Collectors.toList());
        jhVo.setSortDataList(sortedDataList);
        return exportBankUtil.createJhPdf(jhVo);
    }

    /**
     * 获取NH数据列表
     *
     * @param nhVo
     * @return
     */
    @PostMapping("/getNhDetailList")
    public AjaxResult getNhDetailList(@RequestBody NhVo nhVo) {
        log.info("获取NH数据入参：{}", nhVo);
        List<NhPdfDomain> list = extractorBankUtil.compNhDataDetail(nhVo.getStartTime(), nhVo.getEndTime(), nhVo.getOriginalMoney(), nhVo.getTotalInMoney(), nhVo.getTotalOutMoney());
        List<NhPdfDomain> inValueList = new ArrayList<>();
        List<NhPdfDomain> outValueList = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.startsWith(item.getTransactionAmount(), "+")) {
                // 收
                inValueList.add(item);
            } else {
                outValueList.add(item);
            }
        });
        nhVo.setInValueList(inValueList);
        nhVo.setOutValueList(outValueList);
        return AjaxResult.success(nhVo);
    }

    /**
     * 生成PDF文件
     *
     * @param nhVo
     * @throws IOException
     */
    @PostMapping("/createNhPdf")
    public AjaxResult createNhPdf(@RequestBody NhVo nhVo) throws Exception {
        nhVo.setTypeId(1l);
        List<NhPdfDomain> inValueList = nhVo.getInValueList();
        List<NhPdfDomain> outValueList = nhVo.getOutValueList();

        if (!(inValueList != null && !inValueList.isEmpty())) {
            log.info("收入明细数据无效，请检查!");
            return AjaxResult.error("收入明细数据无效，请检查");
        }
        if (!(outValueList != null && !outValueList.isEmpty())) {
            log.info("支出明细数据无效，请检查!");
            return AjaxResult.error("支出明细数据无效，请检查");
        }
        log.info("合并支出并按照时间日期排序...");
        List<NhPdfDomain> needSortDataList = new ArrayList<>();
        needSortDataList.addAll(inValueList);
        needSortDataList.addAll(outValueList);
        List<NhPdfDomain> sortedDataList = needSortDataList.stream().sorted(Comparator.comparingInt(NhPdfDomain::getSortNo)).collect(Collectors.toList());
        nhVo.setSortDataList(sortedDataList);
        return exportBankUtil.createNhPdf(nhVo);
    }

    /**
     * 获取Wx数据列表
     *
     * @param wxVo
     * @return
     */
    @PostMapping("/getWxDetailList")
    public AjaxResult getWxDetailList(@RequestBody WxVo wxVo) {
        log.info("获取Wx数据入参：{}", wxVo);
        List<WxPdfDomain> list = extractorBankUtil.compWxDataDetail(wxVo.getStartTime(), wxVo.getEndTime(), wxVo.getTotalInMoney(), wxVo.getTotalOutMoney());
        List<WxPdfDomain> inValueList = new ArrayList<>();
        List<WxPdfDomain> outValueList = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.startsWith(item.getTransactionAmount(), "+")) {
                // 收
                inValueList.add(item);
            } else {
                outValueList.add(item);
            }
        });
        wxVo.setInValueList(inValueList);
        wxVo.setOutValueList(outValueList);
        return AjaxResult.success(wxVo);
    }

    /**
     * 生成PDF文件
     *
     * @param wxVo
     * @throws IOException
     */
    @PostMapping("/createWxPdf")
    public AjaxResult createWxPdf(@RequestBody WxVo wxVo) throws Exception {
        wxVo.setTypeId(3l);
        List<WxPdfDomain> inValueList = wxVo.getInValueList();
        List<WxPdfDomain> outValueList = wxVo.getOutValueList();

        if (!(inValueList != null && !inValueList.isEmpty())) {
            log.info("收入明细数据无效，请检查!");
            return AjaxResult.error("收入明细数据无效，请检查");
        }
        if (!(outValueList != null && !outValueList.isEmpty())) {
            log.info("支出明细数据无效，请检查!");
            return AjaxResult.error("支出明细数据无效，请检查");
        }
        log.info("合并支出并按照时间日期排序...");
        List<WxPdfDomain> needSortDataList = new ArrayList<>();
        needSortDataList.addAll(inValueList);
        needSortDataList.addAll(outValueList);
        List<WxPdfDomain> sortedDataList = needSortDataList.stream().sorted(Comparator.comparingInt(WxPdfDomain::getSortNo)).collect(Collectors.toList());
        wxVo.setSortDataList(sortedDataList);
        return exportBankUtil.createWxPdf(wxVo);
    }
}
